package org.jash.common.mvi

import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

@Suppress("UNCHECKED_CAST")
open class BaseActivity<D:ViewDataBinding, VM:BaseViewModel<*,*>>:AppCompatActivity() {
    lateinit var binding: D
    lateinit var viewModel: VM
    private lateinit var map: Map<Type, Method>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val type = this.javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val b = type.actualTypeArguments[0] as Class<*>
            val s = type.actualTypeArguments[1] as Class<VM>
            val m = b.getMethod("inflate", LayoutInflater::class.java)
            binding = m.invoke(null, LayoutInflater.from(this)) as D
            viewModel = ViewModelProvider(this)[s]
            setContentView(binding.root)
        }
        map = this.javaClass.declaredMethods
            .filter { it.parameterTypes.size == 1 }
            .filter { BaseState::class.java.isAssignableFrom(it.parameterTypes[0]) }
            .associateBy { it.parameterTypes[0] }
        lifecycleScope.launch {
            viewModel.state.collect {
                collect(it)
            }
        }
    }
    private fun collect(state:BaseState?) {
        state?.let { map[it.javaClass]?.invoke(this, state) }

    }
}